/*-----------------------------------------------------------------------------
 * @file   hal_can.h
 * @brief  Controller Area Network (CAN) driver
 * @author WLH<wanglehui8357@163.com> Copyright (C) 2021~2099
 ----------------------------------------------------------------------------*/
#ifndef HAL_CAN_H
#define HAL_CAN_H

#include "globaldef.h"

BEGIN_DECLS
/*-----------------------------------------------------------------------------
 * CAN Controller Instance ID
-----------------------------------------------------------------------------*/
#define HAL_CAN0     0x00u
#define HAL_CAN1     0x01u
#define HAL_CAN2     0x02u
#define HAL_CAN3     0x03u
#define HAL_CAN_NULL 0xFFu

#define CAN_NODE_MAX         0x03u // Max can node count for each can bus
#define CAN_STD_MAX_DATA_LEN 8u    // Standard CAN data length
#define CAN_FD_MAX_DATA_LEN  64u   // CAN-FD data length
/*-----------------------------------------------------------------------------
 * CAN Bus Baudrate Predefine *
-----------------------------------------------------------------------------*/
/* Nominal bit rate */
#define CAN_NBR_500K 0u /* 500Kbps */
#define CAN_NBR_1M   1u /* 1Mbps   */

/* Data bit rate */
#define CAN_DBR_2M 2u /* 2Mbps */
#define CAN_DBR_4M 4u /* 4Mbps */
#define CAN_DBR_5M 5u /* 5Mbps */
#define CAN_DBR_8M 8u /* 8Mbps */

/*
 * Error Type
 * enum can_async_interrupt_type has 5 fowllowing qualified value
 * 1)CAN_ERR_EW:
 *     Error warning, Error counter has reached the
 *     error warning limit of 96, An error count value
 *     greater than about 96 indicates a heavily disturbed
 *     bus. It may be of advantage to provide means to test
 *     for this condition. Refer to ISO 11898-1 (Bosch CAN
 *     specification 2.0 part A,B)
 * 2)CAN_ERR_EA:
 *     Error Active State, The CAN node normally take
 *     part in bus communication and sends an ACTIVE ERROR
 *     FLAG when an error has been detected.
 *     Refer to ISO 11898-1 (7)
 * 3)CAN_ERR_EP:
 *     Error Passive State, The Can node goes into error
 *     passive state if at least one of its error counters is
 *     greater than 127. It still takes part in bus
 *     activities, but it sends a passive error frame only,
 *     on errors. Refer to ISO 11898-1 (7)
 * 4)CAN_ERR_BO,
 *     Bus Off State, The CAN node is 'bus off' when the
 *     TRANSMIT ERROR COUNT is greater than or equal to 256.
 *     Refer to ISO 11898-1 (7)
 * 5)CAN_ERR_DO
 *     Data Overrun in receive queue. A message was lost
 *     because the messages in the queue was not reading and
 *     releasing fast enough. There is not enough space for
 *     a new message in receive queue.
 */

/*-----------------------------------------------------------------------------
 * CAN Error type
-----------------------------------------------------------------------------*/
typedef enum
{
    CAN_ERR_EW, /* Error warning                 */
    CAN_ERR_EA, /* Error Active State            */
    CAN_ERR_EP, /* Error Passive State           */
    CAN_ERR_BO, /* Bus Off State                 */
    CAN_ERR_DO  /* Data Overrun in receive queue */
} can_error_type;

typedef struct
{
    U32 id;   /* CAN Frame ID           */
    U32 len;  /* CAN data length        */
    U8* data; /* pointer to data buffer */
} can_frame_t;

/*-----------------------------------------------------------------------------
 * Callback functions type when data arrive, invoke in ISR
-----------------------------------------------------------------------------*/
typedef void (*CAN_RX_RDY_CB)(const U8 bus_id, can_frame_t* frame);
typedef void (*CAN_TX_CPLT_CB)(const U8 bus_id);
typedef void (*CAN_ERROR_CB)(const U8 bus_id, can_error_type type);

/*-----------------------------------------------------------------------------
 * public functions
-----------------------------------------------------------------------------*/
/**
 * @brief initialize CAN controller
 * @param[in]  bus_id  The CAN BUS ID @ref HAL_CANx
 */
bool hal_can_init(const U8 bus_id);
/**
 * @brief      register call back function to indicate data is ready
 *
 * @param[in]  bus_id  The CAN BUS ID @ref HAL_CANx
 * @param[in]  cb_fun    The callback function for
 */
void hal_can_reg_rx_ready(const U8 bus_id, CAN_RX_RDY_CB cb_fun);
/**
 * @brief      register call back function to indicate data has been send complete
 * @param[in]  bus_id  The CAN BUS ID @ref HAL_CANx
 * @param[in]  cb_fun    The call back function
 */
void hal_can_reg_tx_cplt(const U8 bus_id, CAN_TX_CPLT_CB cb_fun);
/**
 * @brief      register call back function to indicate canbus error has occur
 * @param[in]  bus_id  The CAN BUS ID @ref HAL_CANx
 * @param[in]  cb_fun    The call back function
 */
void hal_can_reg_err_occur(const U8 bus_id, CAN_ERROR_CB cb_fun);
/**
 * @brief Transmit a data message with a particular message ID
 * @param[in]  bus_id  The CAN BUS ID @ref HAL_CANx
 * @param[in]  msg_id The message id (CAN Frame ID)
 * @param[in]  data   The message data buffer
 * @param[in]  size   The message data length
 */
bool hal_can_transmit(const U8 bus_id, U32 msg_id, U8* data, U8 size);
/**
 * @brief reset canbus controller, must invoking after dev reconnect to canbus.
 * @param[in]  bus_id  The CAN BUS ID @ref HAL_CANx
 */
bool hal_can_reset(const U8 bus_id);
/**
 * @brief Set canbus controller bitrate
 * @param[in]  bus_id  The CAN BUS ID @ref HAL_CANx
 * @param[in]  nbr Nominal bit rate
 * @param[in]  dbr Data bit rate
 */
bool hal_can_set_bitrate(const U8 bus_id, const U8 nbr, const U8 dbr);

END_DECLS

#endif //~HAL_CAN_H
